package ruru.client;

import java.util.Date;
import java.util.List;

import ruru.client.backend.RuruUtility;
import ruru.client.backend.rpcWrapper.TooltipInfoWrapper;
import ruru.client.services.DataService;
import ruru.client.services.DataServiceAsync;
import ruru.client.ui.widgets.BankWidget;
import ruru.client.ui.widgets.ItemLink;
import ruru.client.ui.widgets.PersonalDkpWidget;
import ruru.client.ui.widgets.RaidListWidget;
import ruru.client.ui.widgets.StandingsWidget;
import ruru.client.ui.widgets.roundedTabPanel.RoundedTabPanel;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.WindowResizeListener;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.ServiceDefTarget;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.SourcesTabEvents;
import com.google.gwt.user.client.ui.TabListener;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class RuruDkp implements EntryPoint, WindowResizeListener {
	// private boolean listOutput = true; // toggle for displaying dkp and liquidity in console

	public static RoundedTabPanel body;
	// public static RoundedPanel rpBody;

	private StandingsWidget standings;
	private RaidListWidget raidList;
	private final BankWidget reducks = new BankWidget("Reducks", "Guild Bank");
	// private final VerticalPanel bankList = new VerticalPanel();
	private final static PersonalDkpWidget personalDkp = new PersonalDkpWidget();

	private final HTML news = new HTML();
	private final HTML rules = new HTML();
	private final HTML forums = new HTML();

	// tooltip
	public static HTML tooltip = new HTML();
	public static SimplePanel tooltipPanel = new SimplePanel();
	public static HTML itemIcon = new HTML();
	public static HorizontalPanel tooltipHp = new HorizontalPanel();

	private static String WIDTH = "100%";
	public static final DateTimeFormat dtf = DateTimeFormat.getFormat("EEE MMM dd, yyyy h:mm:ss a");
	public static final Label loading = new Label("Loading...");

	public static long start;

	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad() {
		DateTimeFormat dtf = DateTimeFormat.getFormat("MMM dd, yyyy h:mm:ssa");
		start = System.currentTimeMillis();
		DateTimeFormat.getLongDateTimeFormat();
		System.out.println(dtf.format(new Date()) + " starting client: " + (System.currentTimeMillis() - start) + "ms");

		VerticalPanel rulesPanel = new VerticalPanel();
		rulesPanel.add(rules);

		body = new RoundedTabPanel();
		body.addStyleName("center");

		news.addStyleName("body-text");
		rules.addStyleName("body-text");
		forums.addStyleName("body-text");

		standings = new StandingsWidget();
		body.add(standings, "Standings");
		// body.add(bankList, "Bank");
		body.add(rulesPanel, "Rules");
		body.add(personalDkp, "Individual&nbsp;DKP");
		rules.addStyleName("rules");

		Label bankLoadingLabel = new Label("Loading...");
		// bankList.add(bankLoadingLabel);
		bankLoadingLabel.addStyleName("raid-loading-label");

		body.addTabListener(new TabListener() {
			public boolean onBeforeTabSelected(SourcesTabEvents sender, int tabIndex) {
				return true;
			}

			public void onTabSelected(SourcesTabEvents sender, int tabIndex) {
//				if(tabIndex == body.getWidgetIndex(bankList)) {
//					DeferredCommand.addCommand(new Command() {
//						public void execute() {
//							reducks.getReducksData(bankList, reducks);
//							System.out.println("Opening bank: " + (System.currentTimeMillis() - start) + "ms");
//						}
//					});
//				}

				if(tabIndex == body.getWidgetIndex(personalDkp)) {
					DeferredCommand.addCommand(new Command() {
						public void execute() {
							getLiteRaiderWrappers();
							System.out.println("Loading liteRaiderWrappers: " + (System.currentTimeMillis() - start) + "ms");
						}
					});
				}

				if(tabIndex == body.getWidgetIndex(standings)) {
					DeferredCommand.addCommand(new Command() {
						public void execute() {
							standings.initialize();
						}
					});
				}
			}
		});

		body.setWidth(WIDTH);
		body.selectTab(body.getWidgetIndex(standings));
		body.addStyleName("rurudkp-roundedTabPanel");
		RootPanel.get().add(body);

		tooltipPanel.setVisible(false);

		tooltipHp = new HorizontalPanel();
		tooltipHp.add(itemIcon);
		tooltipHp.add(tooltip);
		tooltipHp.setSpacing(1);
		itemIcon.addStyleName("rurudkp-tooltip-icon");

		tooltipPanel.add(tooltipHp);
		tooltip.addStyleName("rurudkp-tooltip-inner");
		tooltipPanel.addStyleName("rurudkp-tooltip-outer");

		RootPanel.get().add(tooltipPanel);
		RootPanel.get().add(loading, 3, 3);
		loading.addStyleName("loading-label");
		Window.addWindowResizeListener(this);

		/**
		 * Load data asynchronously
		 */
		getRules();
		getRaidTitles();

		if(JSNI.getBrowserWindowWidth() > 950) {
			body.setWidth("900px");
		} else {
			body.setWidth("100%");
		}
	}

	public static void switchToPersonalDkpPage(String raiderName, String raidClass, String capitalName) {
		firePersonalDkpWidget(raiderName, raidClass, capitalName);
		body.selectTab(body.getWidgetIndex(personalDkp));
	}

	public void onWindowResized(int width, int height) {
		// loading.setVisible(true);
		// loading.setText(width + " " + height + " browserWidth: " + JSNI.getBrowserWindowWidth());
		if(JSNI.getBrowserWindowWidth() > 950) {
			body.setWidth("900px");
		} else {
			body.setWidth("100%");
		}
	}

	/**
	 * Opens the personal dkp page with a raider already loaded. Note that personalDkp.load() is called before
	 * personalDkp.openRaiderHistoryPage()
	 * 
	 * @param raiderName
	 * @param raidClass
	 * @param capitalName
	 */
	public static void firePersonalDkpWidget(final String raiderName, final String raidClass, final String capitalName) {
		DataServiceAsync ds = (DataServiceAsync) GWT.create(DataService.class);
		ServiceDefTarget endpoint = (ServiceDefTarget) ds;
		String moduleRelativeURL = GWT.getModuleBaseURL() + "/DataService";
		endpoint.setServiceEntryPoint(moduleRelativeURL);
		AsyncCallback callback = new AsyncCallback() {

			/**/
			public void onSuccess(Object result) {
				List wrappers = (List) result;
				personalDkp.load(wrappers);
				personalDkp.openRaiderHistoryPage(raiderName, raidClass);
				System.out.println("liteRaiderWrappers loaded in client: " + (System.currentTimeMillis() - start) + "ms");
			}

			/**/

			public void onFailure(Throwable caught) {
				System.out.println("in client: getRaidTitles failure");
				caught.printStackTrace();
			}
		};
		ds.getLiteRaiderWrappers(callback);
	}

	public static void getLiteRaiderWrappers() {
		DataServiceAsync ds = (DataServiceAsync) GWT.create(DataService.class);
		ServiceDefTarget endpoint = (ServiceDefTarget) ds;
		String moduleRelativeURL = GWT.getModuleBaseURL() + "/DataService";
		endpoint.setServiceEntryPoint(moduleRelativeURL);
		AsyncCallback callback = new AsyncCallback() {

			/**/
			public void onSuccess(Object result) {
				List wrappers = (List) result;
				personalDkp.load(wrappers);
				System.out.println("liteRaiderWrappers loaded in client: " + (System.currentTimeMillis() - start) + "ms");
			}

			/**/

			public void onFailure(Throwable caught) {
				System.out.println("in client: getRaidTitles failure");
				caught.printStackTrace();
			}
		};
		ds.getLiteRaiderWrappers(callback);
	}

	public void getRaidTitles() {
		DataServiceAsync ds = (DataServiceAsync) GWT.create(DataService.class);
		ServiceDefTarget endpoint = (ServiceDefTarget) ds;
		String moduleRelativeURL = GWT.getModuleBaseURL() + "/DataService";
		endpoint.setServiceEntryPoint(moduleRelativeURL);
		AsyncCallback callback = new AsyncCallback() {

			/**/
			public void onSuccess(Object result) {
				raidList = new RaidListWidget((List) result);
				body.insert(raidList, "Raids", 1);
			}

			/**/

			public void onFailure(Throwable caught) {
				System.out.println("in client: getRaidTitles failure");
				caught.printStackTrace();
			}
		};
		ds.getRaidTitles(callback);
	}

	public void getRules() {
		DataServiceAsync ds = (DataServiceAsync) GWT.create(DataService.class);
		ServiceDefTarget endpoint = (ServiceDefTarget) ds;
		String moduleRelativeURL = GWT.getModuleBaseURL() + "/DataService";
		endpoint.setServiceEntryPoint(moduleRelativeURL);
		AsyncCallback callback = new AsyncCallback() {

			/**/
			public void onSuccess(Object result) {
				rules.setHTML((String) result);
				System.out.println("rules loaded in client: " + (System.currentTimeMillis() - start) + "ms");
			}

			/**/

			public void onFailure(Throwable caught) {
				System.out.println("in client: getRules failure");
				caught.printStackTrace();
			}
		};
		ds.getRules(callback);
	}

	/**
	 * Stuffs item link information from wowhead.com into a tooltip
	 * 
	 * @param url
	 *           The location of the item's info on wowhead
	 * @param tooltip
	 *           The popup window
	 * @param rp
	 *           The rounded border that surrounds the popup window
	 */
	public static void getTooltipInfo(String url, final String item, final ItemLink link) {
		DataServiceAsync ds = (DataServiceAsync) GWT.create(DataService.class);
		ServiceDefTarget endpoint = (ServiceDefTarget) ds;
		String moduleRelativeURL = GWT.getModuleBaseURL() + "/DataService";
		endpoint.setServiceEntryPoint(moduleRelativeURL);
		AsyncCallback callback = new AsyncCallback() {

			/**/
			public void onSuccess(Object result) {
				System.out.println("in client: callback success");
				TooltipInfoWrapper wrapper = (TooltipInfoWrapper) result;
				link.setStorage(wrapper.getInfo());
				link.setIconStorage(wrapper.getIconPath());
				link.setItemRarity(wrapper.getRarity());
			}

			/**/

			public void onFailure(Throwable caught) {
				System.out.println("in client: callback failure");
				loading.setText("Unable to load info for " + RuruUtility.capitalize(RuruUtility.tokenizer(item)));
				loading.setVisible(true);
				Timer t = new Timer() {
					public void run() {
						loading.setVisible(false);
					}
				};
				t.schedule(3000);
			}
		};
		// TODO: make this work for ambiguous regular items too, not just bank items
		// if(item instanceof AmbiguousBankItem) {
		// AmbiguousBankItem abi = (AmbiguousBankItem) item;
		// ds.getTooltipInfo(new Integer(abi.getId()).toString(), true, callback);
		// } else {
		ds.getTooltipInfo(item, false, callback);
		// }
	}
}